import cn.hutool.json.JSONUtil;
import com.sun.org.slf4j.internal.Logger;
import com.sun.org.slf4j.internal.LoggerFactory;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.rocksdb.Options;
import org.rocksdb.RocksDB;
import org.rocksdb.RocksDBException;
import org.rocksdb.RocksIterator;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @description:
 * @author: sali
 * @date: 2025/2/22 下午7:50.
 * @version: 1.0
 */
public class RocksDBUtils {

    private static final Logger log = LoggerFactory.getLogger(RocksDBUtils.class);

    private String dbPath;

    private RocksDB rocksdb;

    public RocksDBUtils(String dbPath) {
        this.dbPath = dbPath;
        try {
            init();
        } catch (Exception e) {
            log.error("rocksdb 初始化失败，路径 {}", dbPath, e);
        }
    }


    public void init() throws IOException, RocksDBException {
        if (StringUtils.isEmpty(dbPath)) {
            throw new IllegalArgumentException("start error, {cache.rocksdbPath} need config");
        }

        try (Options options = new Options();) {
            options.setCreateIfMissing(true);

            // 文件不存在，则先创建文件
            if (!Files.isSymbolicLink(Paths.get(dbPath))) {
                Files.createDirectories(Paths.get(dbPath));
            }

            rocksdb = RocksDB.open(options, dbPath);

            log.debug("Rocks db init successful, path is {}", dbPath);
        }
    }

    public String getAsString(String key) {
        byte[] keyByte = key.getBytes();
        try {
            byte[] bytes = rocksdb.get(keyByte);

            if (bytes == null) {
                return null;
            } else {
                return new String(bytes);
            }
        } catch (RocksDBException e) {
            log.error("rocksdb get error, key {} ", key, e);
        }

        return null;
    }


    public void putString(String key, String value) {
        if (StringUtils.isEmpty(key) || StringUtils.isEmpty(value)) {
            return;
        }
        try {
            rocksdb.put(key.getBytes(), value.getBytes());
        } catch (RocksDBException e) {
            log.error("rocksdb put error, key {} , value {}, error {}", key, value, e);
        }
    }

    public void delete(String key) {
        if (StringUtils.isEmpty(key)) {
            return;
        }

        try {
            rocksdb.delete(key.getBytes());
        } catch (RocksDBException e) {
            log.error("rocksdb delete error, key {} , error {}", key, e);
        }
    }

    public Boolean isExist(String key) {
        return !StringUtils.isEmpty(getAsString(key));
    }

    public RocksIterator getRocketIterator() {
        return rocksdb.newIterator();
    }

    /**
     * description: 查询rocketsDb中的全部数据
     * return: List<Map<String, String>> 返回rocketsDB中的数据结构
     **/
    public List<Map<String, String>> queryAll() {
        List<Map<String, String>> resultMapList = new ArrayList<>();
        RocksIterator rocketIterator = this.getRocketIterator();
        for (rocketIterator.seekToFirst(); rocketIterator.isValid(); rocketIterator.next()) {
            Map<String, String> map = new HashMap<>(1);
            String dataKey = new String(rocketIterator.key());
            String dataValue = new String(rocketIterator.value());
            map.put(dataKey, dataValue);
            resultMapList.add(map);
        }
        return resultMapList;
    }

    /**
     * description: 删除rocketsDb中的全部数据
     **/
    public void deleteAll() {
        RocksIterator rocketIterator = this.getRocketIterator();
        for (rocketIterator.seekToFirst(); rocketIterator.isValid(); rocketIterator.next()) {
            String nfMapKeyWithIamIpCheck = new String(rocketIterator.key());
            this.delete(nfMapKeyWithIamIpCheck);
        }
    }

    /**
     * description: 实现功能如 <key1, value1> --> 指定key1新增value2 --> <key1, (value1, value2)>
     *
     * @param key   原始规则标识
     * @param value 原始规则内容
     **/
    public void putListString(String key, String value) {
        if (StringUtils.isEmpty(key) || StringUtils.isEmpty(value)) {
            return;
        }
        // 读取db中指定key的listString
        String timeStampOrderWithRuleDtoListJson = this.getAsString(key);
        List<String> timeStampOrderWithRuleDtoList = new ArrayList<>();
        if (!StringUtils.isEmpty(timeStampOrderWithRuleDtoListJson)) {
            timeStampOrderWithRuleDtoList = JSONUtil.parseArray(timeStampOrderWithRuleDtoListJson).toList(String.class);
        }
        timeStampOrderWithRuleDtoList.add(value);
        synchronized (this) {
            // 删除旧的db数据
            this.delete(key);
            // 添加新的db数据
            this.putString(key, JSONUtil.toJsonStr(timeStampOrderWithRuleDtoList));
        }
    }

    /**
     * description: 实现功能如 <key, value> --> 删除指定key的指定value
     *
     * @param key   原始规则标识
     * @param value 待删除规则内容
     **/
    public boolean deleteListString(String key, String value) {
        if (StringUtils.isEmpty(key) || StringUtils.isEmpty(value)) {
            return false;
        }
        // 读取db中指定key的listString
        String valueDbListJson = this.getAsString(key);
        if (StringUtils.isEmpty(valueDbListJson)) {
            return false;
        }
        List<String> valueDbList = JSONUtil.parseArray(valueDbListJson).toList(String.class);
        // 在valueDbList中删除指定value
        List<String> valueNewList = valueDbList.stream().filter(valueDb -> !valueDb.equals(value)).collect(Collectors.toList());
        if (valueNewList.isEmpty()) {
            this.delete(key);
        } else {
            this.putString(key, JSONUtil.toJsonStr(valueNewList));
        }
        return true;
    }

}
